#include "heartbeat_model.h"
#include <QDir>
#include <QDateTime>
#include "global_logger.h"

// 心跳模型类的构造函数，继承自QAbstractListModel
HeartbeatModel::HeartbeatModel(QObject *parent) : QAbstractListModel(parent) {
    LOG_INFO("HeartbeatModel 初始化完成");
}

// 实现QAbstractListModel的rowCount方法，用于返回行数
int HeartbeatModel::rowCount(const QModelIndex &parent) const {
    // 如果parent索引有效，则返回0，表示没有子项
    if (parent.isValid()) return 0;
    // 使用QMutexLocker自动管理互斥锁，保护heartbeats_数据的安全访问
    QMutexLocker locker(&mutex_);
    // 返回heartbeats_容器的大小，即心跳信息的数量
    return static_cast<int>(heartbeats_.size());
}

// 实现QAbstractListModel的data方法，用于返回指定索引和角色的数据
QVariant HeartbeatModel::data(const QModelIndex &index, int role) const {
    // 如果索引无效，则返回空的QVariant
    if (!index.isValid()) 
        return QVariant();

    // 使用QMutexLocker自动管理互斥锁，保护heartbeats_数据的安全访问
    QMutexLocker locker(&mutex_);
    const int row = index.row();
    
    // 统一使用int比较，避免size_t与int的符号冲突
    if (row < 0 || row >= static_cast<int>(heartbeats_.size())) 
        return QVariant();

    // 根据行索引获取心跳信息项
    const auto &hb = heartbeats_[static_cast<size_t>(row)];
    // 根据角色返回相应数据
    switch (role) {
        case RobotTypeRole: return hb.robotType;
        case RobotIdRole:   return hb.robotId;
        case TimestampRole: return static_cast<qint64>(hb.timestamp_ms);
        case IsOnlineRole:  return hb.lastOnlineState;
        case StatusRole: return hb.status;
        case BatteryRole: return hb.battery;
        case RobotIPRole: return hb.robotIP;
        case SeerIPRole: return hb.seerIP;
        case CameraIPRole: return hb.cameraUrl;
        case CurrentTargetRole: return hb.currentTarget;
        case CapabilitiesRole: return hb.capabilities;
        default:            return QVariant();
    }
}

// 实现roleNames方法，返回角色名称的哈希表，用于QML或其他视图技术的绑定
QHash<int, QByteArray> HeartbeatModel::roleNames() const {
    // 返回角色名称的哈希表，键为角色枚举值，值为角色名称的字节串
    return {
        {RobotTypeRole, "robotType"},
        {RobotIdRole,   "robotId"},
        {TimestampRole, "timestamp"},
        {IsOnlineRole,  "isOnline"},
        {StatusRole,    "status"},
        {BatteryRole,   "battery"},
        {RobotIPRole,   "robotIP"},
        {SeerIPRole,    "seerIP"},
        {CameraIPRole,  "cameraUrl"},
        {CurrentTargetRole, "currentTarget"},
        {CapabilitiesRole, "capabilities"}  // 添加capabilities角色
    };
}

/**
 * 更新机器人心跳状态信息
 * 
 * 此函数负责更新或添加机器人的心跳信息，包括位置、状态、电池等数据
 * 如果是新机器人则添加到列表中，如果是已有机器人则更新其信息
 * 同时会发出信号通知界面更新显示
 * 
 * @param robotType 机器人类型标识符
 * @param robotId 机器人唯一标识符
 * @param timestamp_us 时间戳（微秒），会被转换为毫秒存储
 * @param status 机器人当前状态（如idle, working, charging等）
 * @param battery 电池电量百分比
 * @param x 机器人在地图上的X坐标
 * @param y 机器人在地图上的Y坐标
 * @param robotIP 机器人控制器的IP地址
 * @param seerIP Seer控制器的IP地址
 * @param cameraUrl 摄像头访问URL
 * @param currentTarget 机器人当前导航目标点
 * @param capabilities 机器人具备的功能类型列表
 */
void HeartbeatModel::updateHeartbeat(
    const QString &robotType, 
    const QString &robotId, 
    uint64_t timestamp_us,
    const QString &status,
    int battery,
    double x, double y,
    const QString &robotIP,
    const QString &seerIP,
    const QString &cameraUrl,
    const QString &currentTarget,
    const QStringList &capabilities)  // 添加capabilities参数
{
    const uint64_t timestamp_ms = timestamp_us / 1000;
    bool found = false;
    int targetIndex = -1;
    QVector<int> rolesToUpdate;

    { 
        QMutexLocker locker(&mutex_);
        for (int i = 0; i < static_cast<int>(heartbeats_.size()); ++i) {
            auto &item = heartbeats_[static_cast<size_t>(i)];
            if (item.robotId == robotId && item.robotType == robotType) {
                found = true;
                
                // 只要收到心跳，就标记为在线
                item.lastOnlineState = true;
                
                // 更新所有字段
                item.timestamp_ms = timestamp_ms;
                item.status = status;
                item.battery = battery;
                item.x = x;
                item.y = y;
                item.robotIP = robotIP;
                item.seerIP = seerIP;
                item.cameraUrl = cameraUrl;
                item.currentTarget = currentTarget;
                item.capabilities = capabilities;  // 更新capabilities字段
                
                targetIndex = i;
                
                // 检查哪些字段发生了变化
                rolesToUpdate << TimestampRole << IsOnlineRole << StatusRole 
                              << BatteryRole << RobotIPRole <<SeerIPRole << CameraIPRole << CurrentTargetRole << CapabilitiesRole;
                break;
            }
        }
    }

    if (!found) {
        LOG_INFO("发现新机器人 - 类型: {}, ID: {}", robotType.toStdString(), robotId.toStdString());
        // 创建机器人资源目录
        ensureRobotDirectories(robotId);

        beginInsertRows(QModelIndex(), rowCount(), rowCount());
        {
            QMutexLocker locker(&mutex_);
            // 完整初始化所有字段
            HeartbeatData newData;
            newData.robotType = robotType;
            newData.robotId = robotId;
            newData.timestamp_ms = timestamp_ms;
            newData.lastOnlineState = true;  // 新机器人默认在线
            newData.status = status;
            newData.battery = battery;
            newData.x = x;
            newData.y = y;
            newData.robotIP = robotIP;
            newData.seerIP = seerIP;
            newData.cameraUrl = cameraUrl;
            newData.currentTarget = currentTarget;
            newData.capabilities = capabilities;  // 初始化capabilities字段
            
            heartbeats_.append(newData);
        }
        endInsertRows();
        LOG_DEBUG("已添加新机器人到列表 - ID: {}", robotId.toStdString());
    } else if (targetIndex != -1) {
        if (!rolesToUpdate.isEmpty()) {
            //LOG_DEBUG("更新机器人 {} 的属性", robotId.toStdString());
            emit dataChanged(
                createIndex(targetIndex, 0), 
                createIndex(targetIndex, 0), 
                rolesToUpdate
            );
        }
    }

    // 发出信号，通知QML更新机器人状态
    emit robotStatusUpdated(robotId, status, currentTarget, battery, x, y);
}

/**
 * 定时检查机器人在线状态
 */
void HeartbeatModel::checkTimeoutSlot(int timeoutSeconds) {
    QVector<int> indexesToOffline;  // 用于标记为离线的机器人
    QVector<int> indexesToRemove;   // 用于完全移除长时间无响应的机器人
    
    // 使用统一的时间基准
    const uint64_t now_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
        std::chrono::steady_clock::now().time_since_epoch()
    ).count();

    {
        QMutexLocker locker(&mutex_);
        for (int i = static_cast<int>(heartbeats_.size()) - 1; i >= 0; --i) {
            auto& item = heartbeats_[static_cast<size_t>(i)];
            // 确保不会出现负数时间差（处理时钟回拨情况）
            uint64_t timeDiff = (now_ms >= item.timestamp_ms) ? (now_ms - item.timestamp_ms) : 0;
            
            // 使用参数 timeoutSeconds 替代硬编码的 15 秒
            if (item.lastOnlineState && timeDiff > static_cast<uint64_t>(timeoutSeconds) * 1000) {
                indexesToOffline.append(i);
            }
            
            // 使用参数 timeoutSeconds 的 4 倍时间替代硬编码的 60 秒（即 4 倍超时时间后移除）
            if (timeDiff > static_cast<uint64_t>(timeoutSeconds) * 4 * 1000) {
                indexesToRemove.append(i);
            }
        }
    }

    // 标记机器人离线
    for (int idx : indexesToOffline) {
        QString robotId;
        {
            QMutexLocker locker(&mutex_);
            robotId = heartbeats_[static_cast<size_t>(idx)].robotId;
            heartbeats_[static_cast<size_t>(idx)].lastOnlineState = false;
        }
        LOG_INFO("机器人 {} 超时，标记为离线", robotId.toStdString());
        
        emit dataChanged(
            createIndex(idx, 0), 
            createIndex(idx, 0), 
            QVector<int>({IsOnlineRole})
        );
        
        // 发出信号，通知QML机器人离线
        emit robotStatusUpdated(robotId, "OFFLINE", "", 0, 0.0, 0.0);
    }
    
    // 移除长时间没有心跳的机器人
    for (int idx : indexesToRemove) {
        QString robotId;
        {
            QMutexLocker locker(&mutex_);
            robotId = heartbeats_[static_cast<size_t>(idx)].robotId;
        }
        LOG_INFO("机器人 {} 长时间无响应，从列表中移除", robotId.toStdString());
        beginRemoveRows(QModelIndex(), idx, idx);
        {
            QMutexLocker locker(&mutex_);
            heartbeats_.erase(heartbeats_.begin() + idx);
        }
        endRemoveRows();
    }
    
    if (!indexesToOffline.isEmpty() || !indexesToRemove.isEmpty()) {
        LOG_DEBUG("本轮超时检查完成，标记 {} 个机器人离线，移除 {} 个机器人", 
                           indexesToOffline.size(), indexesToRemove.size());
    }
}

/**
 * 处理心跳信号槽函数
 */
void HeartbeatModel::handleHeartbeatSlot(const QVariantMap &robotData) {
    QString robotType = robotData["robotType"].toString();
    QString robotId = robotData["robotId"].toString();
    uint64_t timestamp = robotData["timestamp"].toULongLong();
    QString status = robotData.value("status", "idle").toString();
    int battery = robotData.value("battery", 0).toInt();
    double x = robotData.value("x", 0.0).toDouble();
    double y = robotData.value("y", 0.0).toDouble();
    QString robotIP = robotData.value("robotIP", "").toString();
    QString seerIP = robotData.value("seerIP", "").toString();
    QString cameraUrl = robotData.value("cameraUrl", "").toString();
    QString currentTarget = robotData.value("currentTarget", "").toString();
    QStringList capabilities = robotData.value("capabilities", QStringList()).toStringList();  // 获取capabilities字段
    
    // 将capabilities列表转换为字符串用于日志输出
    QString capabilitiesStr = capabilities.join(", ");
    if (capabilitiesStr.isEmpty()) {
        capabilitiesStr = "无";
    }
    
    /*LOG_DEBUG("处理心跳信号 - 机器人: {}, ID: {}, 状态: {}, 电量: {}%", 
                        robotType.toStdString(), robotId.toStdString(), 
                        status.toStdString(), battery);*/
    //LOG_DEBUG("机器人功能类型列表: {}", capabilitiesStr.toStdString());
    
    // 调用更新函数
    updateHeartbeat(robotType, robotId, timestamp, status, battery, x, y, robotIP, seerIP, cameraUrl, currentTarget,capabilities);
}

/**
 * @brief 确保机器人的相关目录结构存在
 */
void HeartbeatModel::ensureRobotDirectories(const QString &robotId) {
    if (robotId.isEmpty()) return;
    
    // 获取可执行程序所在目录
    QDir execDir(QDir::currentPath());
    QString resourcePath = execDir.absoluteFilePath("data");
    
    // 创建 data 目录（如果不存在）
    QDir resourceDir(resourcePath);
    if (!resourceDir.exists()) {
        if (execDir.mkdir("data")) {
            LOG_DEBUG("创建 data 目录");
        } else {
            LOG_WARN("创建 data 目录失败");
        }
    }
    
    // 创建机器人特定目录（如果不存在）
    QString robotDirPath = resourceDir.absoluteFilePath(robotId);
    QDir robotDir(robotDirPath);
    if (!robotDir.exists()) {
        if (resourceDir.mkdir(robotId)) {
            LOG_DEBUG("为机器人 {} 创建目录", robotId.toStdString());
        } else {
            LOG_WARN("为机器人 {} 创建目录失败", robotId.toStdString());
        }
    }
    
    // 创建 map 子目录（如果不存在）
    QString mapDirPath = robotDir.absoluteFilePath("map");
    QDir mapDir(mapDirPath);
    if (!mapDir.exists()) {
        if (robotDir.mkdir("map")) {
            LOG_DEBUG("为机器人 {} 创建 map 子目录", robotId.toStdString());
        } else {
            LOG_WARN("为机器人 {} 创建 map 子目录失败", robotId.toStdString());
        }
    }
}
